package dmxGroupControl.solvers;

import dmxGroupControl.Fixture;
import dmxGroupControl.FixtureType;
import dmxGroupControl.Group;
import dmxGroupControl.pixels.PixelMath;
import org.jdom2.Attribute;

import java.util.*;
import java.util.stream.Collectors;

public class ApeShitSolver
    extends Solver
{
    private static List<String> solvableChannels = Arrays.asList(
        "Red", "Green", "Blue", "White", "MonoMaster");
    private static List<String> solvableAttributes = Arrays.asList("Chase");

    float value;
    int countdown;
    int countdownFrames;
    Random random;
    ArrayList<Fixture> applicableFixtures;
    Fixture activeFixture;

    public ApeShitSolver(Group group, int countdownFrames)
    {
        enabled = false;
        this.countdownFrames = countdownFrames;
        this.countdown = 0;
        random = new Random();

        applicableFixtures = new ArrayList<>();

        applicableFixtures.addAll(
            group.GetFixtures()
                .stream()
                .filter(ApeShitSolver::GetIsApplicableToFixture)
                .collect(Collectors.toList())
        );
        enabled = true;
    }

    public static boolean GetIsApplicableToFixture(Fixture fixture)
    {
        return fixture.GetFixtureType() == FixtureType.LED
            && Solver.GetIsApplicableToFixture(fixture, solvableChannels);
    }

    @Override
    public String GetType()
    {
        return "apeshit";
    }

    @Override
    public void Set(String attributeName, float value)
    {
        if (attributeName.equalsIgnoreCase("apeshit"))
        {
            this.value = value;
            if (value == 0.0f)
            {
                countdown = 0;
            }
        }
    }

    @Override
    public boolean SolvesAttribute(String attribute)
    {
        return (attribute.equalsIgnoreCase("Apeshit"));
    }

    @Override
    protected void SolveInternal()
    {
        if (applicableFixtures.size() <= 0 || value == 0.0f)
        {
            return;
        }
        countdown--;
        if (countdown <= 0)
        {
            float trueCountdown = PixelMath.Clamp(countdownFrames / value, 0, 20f);
            countdown = Math.round(trueCountdown);
            int fixtureNumber = random.nextInt(applicableFixtures.size());
            Fixture previousFixture = activeFixture;
            activeFixture = applicableFixtures.get(fixtureNumber);
            if(activeFixture == previousFixture)
            {
                activeFixture = null;
            }
        }

        applicableFixtures
            .stream()
            .filter(fixture -> activeFixture != fixture)
            .flatMap(fixture -> fixture.GetChannels().stream())
            .filter(channel -> Solver.SolvesForChannel(channel.GetName(), solvableChannels))
            .forEach(channel -> channel.SetValue(0.0f));

    }

    @Override
    public float GetAttribute(String name)
    {
        if (name.equals("apeshit"))
        {
            return value;
        }
        return 0.0f;
    }

    @Override
    public Collection<? extends Attribute> GetAttributes()
    {
        ArrayList<Attribute> attributes = new ArrayList<>();
        attributes.add(new Attribute("countdownFrames", countdownFrames + ""));
        return attributes;
    }

}
